package com.uobgroup.ews.uam.web;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import com.google.gson.Gson;
import com.uobgroup.ews.uam.core.domain.ApplicationConfiguration;
import com.uobgroup.ews.uam.core.domain.Profile;
import com.uobgroup.ews.uam.core.domain.UAMUser;
import com.uobgroup.ews.uam.core.model.Person;
import com.uobgroup.ews.uam.core.service.ApplicationConfigurationService;
import com.uobgroup.ews.uam.core.service.ProfileService;
import com.uobgroup.ews.uam.core.service.ReferenceService;
import com.uobgroup.ews.uam.core.service.UAMUserService;
import com.uobgroup.ews.uam.core.service.ldap.ADService;
import com.uobgroup.ews.uam.core.service.ldap.LDSService;
import com.uobgroup.ews.uam.web.dto.ProfileJsonItem;
import com.uobgroup.ews.uam.web.dto.ProfileJsonObject;
import com.uobgroup.ews.uam.web.dto.SearchUser;
import com.uobgroup.ews.uam.web.dto.UAMUserFilter;

@RequestMapping("/uamusers")
@Controller
public class UAMUserController {

   @Autowired
   UAMUserService uAMUserService;

   @Autowired
   ProfileService profileService;

   @Autowired
   ADService adService;

   @Autowired
   LDSService ldsService;

   @Autowired
   ApplicationConfigurationService applicationConfigService;

   @Autowired
   ReferenceService referenceService;

   public static final int NO_SEARCH = 0;

   public static final int SEARCH_EXIST = 1;

   public static final int SEARCH_NOT_FOUND = -1;

   public static final int SEARCH_FOUND = 2;

   public static final String USERNAME_NOT_FOUND_IN_AD = "Username not found in AD";

   public static final String USERNAME_EXIST = "Username already created";

   public static final String USERNAME_DOMAIN = "username.domain";

   @RequestMapping(method = RequestMethod.POST, produces = "text/html", params = "Save")
   public String create(@Valid UAMUser UAMUser_, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest) {

      if (UAMUser_.getSearchUsername() != "") {

         if (!uAMUserService.IsExitUser(UAMUser_.getSearchUsername())) {

            Person person = null;
            try {
               person = adService.findUser(UAMUser_.getSearchUsername());
            }
            catch (Exception e) {

            }
            if (person != null) {

               // Set Firstname = Lastname = username // suggest by Julian
               person.setFirstName(UAMUser_.getSearchUsername());
               person.setLastName(UAMUser_.getSearchUsername());

               // set Country for proxy user, country should be 2 letters
               person.setCountry(UAMUser_.getCountry().getCode());

               Profile profile = profileService.findProfileById(UAMUser_.getProfile().getId());
               UAMUser_.setProfile(profile);

               UAMUser_.setProxyUser(person.getSid());
               UAMUser_.setIsDeleted(false);
               UAMUser_.setIsLocked(false);
               UAMUser_.setUsername(UAMUser_.getSearchUsername());

               try {
                  ldsService.createUser(person);
               }
               catch (Exception e) {
                  return "redirect:/uamusers/create";
               }

               uiModel.asMap().clear();
               uAMUserService.saveUAMUser(UAMUser_);
               return "redirect:/uamusers/view/"
                     + encodeUrlPathSegment(UAMUser_.getId().toString(), httpServletRequest);
            }
         }

         if (uAMUserService.IsExitUser(UAMUser_.getSearchUsername())) {

            return "redirect:/uamusers/view/"
                  + encodeUrlPathSegment(uAMUserService.findUserbyUsername(UAMUser_.getSearchUsername()).getId()
                        .toString(), httpServletRequest);
         }
      }

      return "redirect:/uamusers/create";
   }

   @RequestMapping(value = "/create", produces = "text/html")
   public String createForm(Model uiModel) {
      populateEditForm(uiModel, new UAMUser(), false, NO_SEARCH);
      return "uamusers/create";
   }

   @RequestMapping(value = "view/{id}", produces = "text/html")
   public String show(@PathVariable("id") Long id, Model uiModel) {
      uiModel.addAttribute("uamuser_", uAMUserService.findUAMUser(id));
      uiModel.addAttribute("itemId", id);
      return "uamusers/show";
   }

   @RequestMapping(produces = "text/html")
   public String list(@RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel, UAMUserFilter listFilter) {
      int sizeNo = size == null ? 10 : size.intValue();
      final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
      /* float nrOfPages = 0; */

      // if (page != null || size != null) {
      /*
       * int sizeNo = size == null ? 10 : size.intValue(); final int firstResult
       * = page == null ? 0 : (page.intValue() - 1) * sizeNo;
       */
      listFilter = new UAMUserFilter();
      listFilter.setUserList(uAMUserService.findUAMUserEntries(firstResult, sizeNo));
      uiModel.addAttribute("listFilter", listFilter);
      float nrOfPages = (float) uAMUserService.countAllUAMUsers() / sizeNo;
      uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
            : nrOfPages));
      /*
       * } else {
       * 
       * listFilter = new UAMUserFilter();
       * listFilter.setUserList(uAMUserService.findAllUAMUsers());
       * uiModel.addAttribute("listFilter", listFilter);
       * 
       * }
       */
      return "uamusers/list";
   }

   @RequestMapping(value = "/uamuserssearch", method = RequestMethod.POST)
   public String uamuserssearch(@RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel, UAMUserFilter _userFilter) {

      return getSearchData(size, page, uiModel, _userFilter);
   }

   public String getSearchData(Integer size, Integer page, Model uiModel, UAMUserFilter _userFilter) {
      /*
       * if (page == null) { page = 1; } if (size == null) { size = 10; }
       */
      int sizeNo = size == null ? 10 : size.intValue();
      final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;

      List<UAMUser> listuser = uAMUserService.findUAMUserFilter(_userFilter.getSearchusername(),
            _userFilter.getIsAdmin(), _userFilter.getIsActive(), _userFilter.getIsDeleted(), _userFilter.getIsLocked(),
            firstResult, sizeNo);

      long countUsers = uAMUserService.countUAMUserFilter(_userFilter.getSearchusername(), _userFilter.getIsAdmin(),
            _userFilter.getIsActive(), _userFilter.getIsDeleted(), _userFilter.getIsLocked());
      
      float nrOfPages = (float) countUsers / sizeNo;
      uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
            : nrOfPages));
      _userFilter.setUserList(listuser);
      uiModel.addAttribute("listFilter", _userFilter);
      return "uamusers/list";

   }

   @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
   public String update(@Valid UAMUser UAMUser_, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest) {

      UAMUser _uam = uAMUserService.findUAMUser(UAMUser_.getId());
      Profile profile = profileService.findProfileById(UAMUser_.getProfile().getId());

      UAMUser_.setProxyUser(_uam.getProxyUser());
      UAMUser_.setUsername(_uam.getUsername());
      UAMUser_.setDomain(_uam.getDomain());
      UAMUser_.setProfile(profile);
      UAMUser_.setLastLogonDate(_uam.getLastLogonDate());

      uiModel.asMap().clear();
      uAMUserService.updateUAMUser(UAMUser_);
      return "redirect:/uamusers/view/" + encodeUrlPathSegment(UAMUser_.getId().toString(), httpServletRequest);
   }

   @RequestMapping(value = "/update/{id}", method = RequestMethod.GET)
   public String updateForm(@PathVariable("id") Long id, Model uiModel) {
      UAMUser _uamUser = uAMUserService.findUAMUser(id);

      populateEditForm(uiModel, _uamUser, _uamUser.getIsAdmin(), NO_SEARCH);
      return "uamusers/update";
   }

   @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
   public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      UAMUser UAMUser_ = uAMUserService.findUAMUser(id);
      uAMUserService.deleteUAMUser(UAMUser_);
      uiModel.asMap().clear();
      uiModel.addAttribute("page", (page == null) ? "1" : page.toString());
      uiModel.addAttribute("size", (size == null) ? "10" : size.toString());
      return "redirect:/uamusers";
   }

   void populateEditForm(Model uiModel, UAMUser UAMUser_, boolean flag, int status) {

      List<ApplicationConfiguration> lsAppConfig = applicationConfigService.findUsernameDomain(USERNAME_DOMAIN);

      uiModel.addAttribute("domain", lsAppConfig);

      if (flag)
         uiModel.addAttribute("profiles", profileService.findAdminRole());
      else
         uiModel.addAttribute("profiles", profileService.findNonAdminRole());

      if (status == 0) {
         uiModel.addAttribute("message", "");
      }
      else if (status == 1) {
         uiModel.addAttribute("message", USERNAME_EXIST);
      }
      else if (status == -1) {
         uiModel.addAttribute("message", USERNAME_NOT_FOUND_IN_AD);
      }

      uiModel.addAttribute("user_", new SearchUser());
      uiModel.addAttribute("UAMUser_", UAMUser_);
      uiModel.addAttribute("country", referenceService.findAllCountrys());

   }

   String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
      String enc = httpServletRequest.getCharacterEncoding();
      if (enc == null) {
         enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
      }
      try {
         pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
      }
      catch (UnsupportedEncodingException uee) {
      }
      return pathSegment;
   }

   @RequestMapping(method = RequestMethod.POST, produces = "text/html", params = "SearchButton")
   String searchUser(@Valid UAMUser UAMUser_, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest) {

      String username = UAMUser_.getUsername();
      if (username != "") {

         try {
            if (uAMUserService.IsExitUser(username)) {

               UAMUser uamuser = new UAMUser();
               uamuser.setUsername(UAMUser_.getUsername());
               populateEditForm(uiModel, uamuser, false, SEARCH_EXIST); // exist
               return "uamusers/create";
            }
            else {

               try {
                  Person person = null;
                  person = adService.findUser(username);
                  if (person == null) {

                     UAMUser uamuser = new UAMUser();
                     uamuser.setUsername(UAMUser_.getUsername());
                     populateEditForm(uiModel, uamuser, false, SEARCH_NOT_FOUND); // not
                                                                                  // found
                     return "uamusers/create";

                  }
                  else {
                     UAMUser uamuser = new UAMUser();
                     uamuser.setSearchUsername(UAMUser_.getUsername());
                     uamuser.setUsername(UAMUser_.getUsername());
                     populateEditForm(uiModel, uamuser, false, SEARCH_FOUND); // found
                     uiModel.addAttribute("person", person);
                     return "uamusers/create";
                  }

               }
               catch (Exception e) {
                  return "redirect:/uamusers/create";
               }
            }

         }
         catch (Exception e) {
            return "redirect:/uamusers/create";
         }
      }
      return "redirect:/uamusers/create";

   }

   @RequestMapping(method = RequestMethod.GET, value = "/populateprofileadmin/{id}", headers = "Accept=application/json")
   public @ResponseBody
   String getProfiles(@PathVariable("id") String id) {

      List<Profile> list = new ArrayList<Profile>();
      if (id.equals(new String("true")))
         list = profileService.findAdminRole();
      else
         list = profileService.findNonAdminRole();

      ProfileJsonObject obj = new ProfileJsonObject();
      obj.setIdentifier("id");
      obj.setLabel("name");
      List<ProfileJsonItem> items = new ArrayList<ProfileJsonItem>();

      for (Profile profile : list) {
         items.add(new ProfileJsonItem(profile.getId(), profile.getName()));
      }
      obj.setItems(items);
      Gson gson = new Gson();
      return gson.toJson(obj);
   }

}
